local skynet = require "skynet"
local filelog = require "filelog"
local timer = require "timer"
local timetool = require "timetool"
local tabletool = require "tabletool"
local base = require "base"
local qhbtool = require "qhbtool"
require "hbslenum"

local server = nil
local gamelogic = {}

function gamelogic.init(service)
	if server == nil then server = service end
end

function gamelogic.initstate(gameobj, tableobj)
	gameobj.tableobj = tableobj
    gameobj.stateevent[HBSLTableState.TABLE_STATE_GAME_START] = gamelogic.game_start
    gameobj.stateevent[HBSLTableState.TABLE_STATE_ONE_GAME_START] = gamelogic.one_game_start
    gameobj.stateevent[HBSLTableState.TABLE_STATE_PLAYER_QHB] = gamelogic.player_qhb
    gameobj.stateevent[HBSLTableState.TABLE_STATE_ONE_GAME_END] = gamelogic.one_game_end
    gameobj.stateevent[HBSLTableState.TABLE_STATE_ONE_GAME_END_AFTER] = gamelogic.one_game_end_after
end

function gamelogic.run(gameobj)
    local f = nil
    local loopcount = 1
    while true do
        if gameobj.tableobj.state == HBSLTableState.TABLE_STATE_WAIT_PLAYER_BURY_LANDMINE then
            break
        end
        f = gameobj.stateevent[gameobj.tableobj.state]
        if f == nil then
            break
        end
        if loopcount <= 0 then
            break
        end
        f(gameobj)
        loopcount = loopcount - 1
    end
end

function gamelogic.send_gamestart_notice(gameobj)
    local tableobj = gameobj.tableobj
    local tablelogic = server:get_logicbyname("tablelogic")
    --[[
    message table_gameinfo {
        optional table_conf         tableconf           = 1;
        optional table_baseinfo     tablebaseinfo       = 2;
        optional bury_landmineinfo  burylandmineinfo    = 3;        //当前可以抢的红包（一般模式用）
        repeated seat_roleinfo      seatroleinfos       = 4;        //抢红包的玩家的信息
        repeated seat_gameinfo      seatgameinfos       = 5;        //抢红包的玩家信息
        optional seat_roleinfo      selfroleinfo        = 6;        // 玩家自己的信息  
        optional seat_gameinfo      selfgameinfo        = 7;        // 玩家自己的信息
        optional todo_info          todoinfo            = 8;        //
        repeated bury_landmineinfo  can_gethbsinfo      = 9;        //可以抢的红包（无限模式用，有多个红包）
        repeated get_hb_num_list    hb_num_lists        = 10;       // 枪红包数量排行 (无限模式使用)
        repeated get_hb_money_list  hb_money_lists      = 11;       // 抢红包金额排行 (无限模式使用)   
    }
    //通知玩家开始游戏
    message gamestartN {
        optional table_gameinfo game_info = 1;
    }
    --]]
    local noticemsg = {
        game_info = {
            tableconf = {},
            tablebaseinfo = {},
            burylandmineinfo = {},
            seatroleinfos = {},
            seatgameinfos = {},
            selfroleinfo = {},
            selfgameinfo = {},
            todoinfo = {},
            can_gethbsinfo = {},
            hb_num_lists = {},
            hb_money_lists = {},
        },
    }
    tablelogic.copy_tablegameinfo(noticemsg.game_info)
    for index, seat in ipairs(tableobj.seats) do
        if seat.rid ~= 0 then
            noticemsg.game_info.selfroleinfo = {}
            noticemsg.game_info.selfgameinfo = {}
            noticemsg.game_info.todoinfo = {}
            tablelogic.copy_roleinfo(noticemsg.game_info.selfroleinfo, seat)
            tablelogic.copy_gameinfo(noticemsg.game_info.selfgameinfo, seat)
            local now_time = timetool.get_time()
            local todo_info = noticemsg.game_info.todoinfo
            if tableobj.action_to_time > now_time then
                todo_info.rid = seat.rid
                todo_info.action_to_time = tableobj.action_to_time
                todo_info.action_type = tableobj.action_type
            end
            server:send_notice_to_players({seat.rid}, "gamestartN", noticemsg, nil, nil)
        end
    end
end

function gamelogic.game_start(gameobj)
	---filelog.sys_error("-------gamelogic.game_start------")
    local tableobj = gameobj.tableobj
    tableobj.state = HBSLTableState.TABLE_STATE_WAIT_PLAYER_BURY_LANDMINE
    local tablelogic = server:get_logicbyname("tablelogic")
    local tablerobothelper = server:get_logicbyname("tablerobothelper")
    if tableobj.conf.play_game_type == HBSLPlayGameType.GMAE_TYPE_UNLIMIT then
        local timerntc = {
            table_index = tableobj.conf.table_index,
        }
        tableobj.unlimit_check_hbover_timer = timer.settimer(1 * 100, "check_unlimit_qhb_outtime", timerntc)
        skynet.fork(function()
            while true do
                tablelogic.check_nolimit_hbstate()
                skynet.sleep(0.5 * 100)
            end
            end)
        skynet.fork(function()
            while true do
                tablerobothelper.check_hbinfo_for_robot_nolimit()
                skynet.sleep(30)
            end
        end)
    end
end

function gamelogic.one_game_start(gameobj)
	---filelog.sys_error("------gamelogic.one_game_start---------")
	local tableobj = gameobj.tableobj
	---tableobj.state = HBSLTableState.TABLE_STATE_WAIT_PLAYER_BURY_LANDMINE
    tableobj.one_start_time = timetool.get_time()
    local tablelogic = server:get_logicbyname("tablelogic")
    tablelogic.onegamestart_init_tablerecord()
    local tablerobothelper = server:get_logicbyname("tablerobothelper")
    tablerobothelper.check_robot_numer()
    ---发送gamestartN
    gamelogic.send_gamestart_notice(gameobj)

    local noticemsg = {
        table_index = tableobj.conf.table_index,
    }
    tableobj.timer_id = timer.settimer(10, "one_game_start_over", noticemsg)
    tableobj.state = HBSLTableState.TABLE_STATE_ONE_GAME_START_OVER
    tableobj.check_mlinfo_timer_id = timer.settimer(100, "check_mlplayerinfo", noticemsg)
end

function gamelogic.player_qhb(gameobj)
    ---filelog.sys_error("-----------gamelogic.player_qhb--------------")
    local tableobj = gameobj.tableobj
    local tablelogic = server:get_logicbyname("tablelogic")
    ---发送玩家可以抢红包通知
    --[[
        //通知玩家操作
    message todoN {
        optional int32 rid = 1;
        optional int32 action_to_time = 2;  //玩家操作到期时间
        optional int32 action_type = 3;
    }
    --]]
    local todontc = {
        rid = 0,
        action_to_time = timetool.get_time() + tableobj.conf.action_qianghb_time,
        action_type = HBSLActionType.ACTION_TYPE_QHB,
    }
    tableobj.action_to_time = timetool.get_time() + tableobj.conf.action_qianghb_time
    tableobj.action_type = HBSLActionType.ACTION_TYPE_QHB

    local bury_landmineplayer = tableobj.cur_landmineinfo

    for index, seat in ipairs(tableobj.seats) do
        if seat.rid ~= 0 then
            todontc.rid = seat.rid
            server:send_notice_to_players({seat.rid}, "todoN", todontc, nil, nil)
            if bury_landmineplayer.rid == seat.rid then
                seat.no_curbury_round = 0
            else
                local has_buryinfo = tablelogic.get_bury_info_byrid(seat.rid)
                if has_buryinfo and seat.playerinfo.level == 99 then
                    seat.no_curbury_round = seat.no_curbury_round + 1 
                end
            end
        end
    end
    local noticemsg = {
        table_index = tableobj.conf.table_index,
    }
    tableobj.timer_id = timer.settimer(tableobj.conf.action_qianghb_time * 100, "player_qhb_outoftime", noticemsg)

    local chfrntc = {
        table_index = tableobj.conf.table_index,
    }
    tableobj.check_hbinfo_timer_id = timer.settimer(3, "check_hbinfo_for_robot", chfrntc)
    tableobj.state = HBSLTableState.TABLE_STATE_WAIT_PLAYER_QHB
end

function gamelogic.one_game_end(gameobj)
    ---filelog.sys_error("-----------gamelogic.one_game_end-----------")
    local tableobj = gameobj.tableobj
    local tablelogic = server:get_logicbyname("tablelogic")
    tableobj.one_end_time = timetool.get_time()
    tablelogic.balance()
    local noticemsg = {
        table_index = tableobj.conf.table_index,
    }
    tableobj.timer_id = timer.settimer(50, "one_game_end_over", noticemsg)
    tableobj.state = HBSLTableState.TABLE_STATE_ONE_GAME_END_OVER
end

function gamelogic.one_game_end_after(gameobj)
    local tableobj = gameobj.tableobj
    local seatlogic = server:get_logicbyname("seatlogic")
    local tablelogic = server:get_logicbyname("tablelogic")
    tablelogic.save_table_records()
    local tablerobothelper = server:get_logicbyname("tablerobothelper")
    local is_table_end = tableobj.table_end_flag
    if is_table_end == true then
        tablelogic.resetdata()
        tableobj.state = HBSLTableState.TABLE_STATE_GAME_START_OVER
        if tableobj.delete_table_timer_id > 0 then
            timer.cleartimer(tableobj.delete_table_timer_id)
            tableobj.delete_table_timer_id = -1
        end
        if tableobj.delete_table_timer_id == -1 then
            local noticemsg = {
                table_index = tableobj.conf.table_index,
                reason = "tableend",
            }
            tableobj.delete_table_timer_id = timer.settimer(1*100, "delete_table", noticemsg)
        end
        return 
    end 
    tablelogic.resetdata()
    tablerobothelper.check_cancel_bury()
    tablelogic.check_player_is_leave()
    tablerobothelper.check_robot_leave()

    for index, seat in ipairs(tableobj.seats) do
        if seat.rid ~= 0 and seat.state == HBSLSeatState.SEAT_STATE_PLAYING then
            seatlogic.resetstate(seat)
        end
    end
    if #tableobj.wantbury_landmineinfo > 0 then
        local timerntc = {
            table_index = tableobj.conf.table_index,
        }
        tableobj.timer_id = timer.settimer(10, "one_game_end_after_tostart", timerntc)
        tableobj.state = HBSLTableState.TABLE_STATE_ONE_GAME_END_AFTER_OVER
    else
        tableobj.state = HBSLTableState.TABLE_STATE_WAIT_PLAYER_BURY_LANDMINE
    end
end

function gamelogic.add_newhb_nolimit(gameobj)
    local tableobj = gameobj.tableobj
    local tablelogic = server:get_logicbyname("tablelogic")
    local seatlogic = server:get_logicbyname("seatlogic")
    local tablerobothelper = server:get_logicbyname("tablerobothelper")

    local can_qiang_landminenum = tablelogic.get_can_qiang_landminenum()
    if can_qiang_landminenum < 5 then
        local get_bury_landmindnum = 5 - can_qiang_landminenum
        local get_bury_landmines = tablelogic.get_online_bury_bynum(get_bury_landmindnum)
        if #get_bury_landmines > 0 then
            --[[
                newhbsN
                // 新红包通知(无限模式才有)
            // 埋雷信息(发红包的相关信息)
            message bury_landmineinfo {
                optional string         hb_id               = 1;            //红包id(有多个红包 无限模式 使用)
                optional int32          rid                 = 2;            // 发红包玩家rid
                optional string         rolename            = 3;            // 发红包玩家名字
                optional string         logo                = 4;            //发红包玩家头像
                optional int32          sex                 = 5; 
                optional int32          total_money         = 6;            // 红包总金额
                optional int32          left_hb_num         = 7;            // 剩余红包数
                optional int32          all_hb_num          = 8;            // 红包总个数
                optional int32          landmine_num        = 9;            // 雷号
                optional int32          times               = 10;           // 倍数
                optional int32          get_money           = 11;           // 获利多少(结算时使用)
                repeated seat_gameinfo  qiang_hb_players    = 12;           // 抢过该红包的玩家列表(无限模式使用 一般模式不用)
                repeated seat_gameinfo  add_qhb_players     = 13;           // 抢红包的玩家增量列表(无限模式使用 一般模式不用)
            }
            message newhbsN {
                repeated bury_landmineinfo idle_hbs = 1; //
            }
            --]]
            local newhbs_data = {
                idle_hbs = {},
            }
            --[[
                message qhb_action {
                    optional string hb_id = 1;
                    optional int32  action_outtime = 2;
                }
                //通知玩家操作
                message todoN {
                    optional int32 rid = 1;
                    optional int32 action_to_time = 2;  //玩家操作到期时间
                    optional int32 action_type = 3;
                    repeated qhb_action qhbs   = 4;     // 可抢红包id和超时时间
                }
            --]]
            local now_time = timetool.get_time()
            local qhb_action_time = tableobj.conf.action_qianghb_time
            local newhbs_tododata = {
                rid = 0,
                action_to_time = now_time + qhb_action_time,
                action_type = HBSLActionType.ACTION_TYPE_QHB,
                qhbs = {},
            }

            for index, get_bury_landmine in ipairs(get_bury_landmines) do
                local temp_cur_landmineinfo = {}
                temp_cur_landmineinfo.hb_id             = get_bury_landmine.hb_id
                temp_cur_landmineinfo.rid               = get_bury_landmine.rid
                temp_cur_landmineinfo.rolename          = get_bury_landmine.rolename
                temp_cur_landmineinfo.logo              = get_bury_landmine.logo
                temp_cur_landmineinfo.sex               = get_bury_landmine.sex
                temp_cur_landmineinfo.total_money       = get_bury_landmine.total_money
                temp_cur_landmineinfo.total_hb_num      = get_bury_landmine.total_hb_num
                temp_cur_landmineinfo.landmine_num      = get_bury_landmine.landmine_num
                temp_cur_landmineinfo.times             = get_bury_landmine.times or 1
                temp_cur_landmineinfo.already_qhb_num   = 0
                temp_cur_landmineinfo.is_over           = false
                temp_cur_landmineinfo.action_outtime    = now_time + qhb_action_time
                temp_cur_landmineinfo.one_start_time    = timetool.get_time()
                temp_cur_landmineinfo.one_end_time     = 0
                local get_leinum = skynet.call(".slotmgr", "lua", "get_leinum_nums", temp_cur_landmineinfo.total_hb_num)
                local min_hb_money = base.get_random(18,27)
                local real_min_money = math.floor(temp_cur_landmineinfo.total_money/100)
                if real_min_money > min_hb_money then
                    min_hb_money = real_min_money
                end
                temp_cur_landmineinfo.wait_qhbinfos = qhbtool.gen_all_hbinfos_bylandnum(temp_cur_landmineinfo.total_money,
                    temp_cur_landmineinfo.total_hb_num, min_hb_money, math.floor(temp_cur_landmineinfo.total_money * 2 / temp_cur_landmineinfo.total_hb_num),
                        temp_cur_landmineinfo.landmine_num, get_leinum, get_leinum)

                table.insert(tableobj.can_qiang_landmineinfos, temp_cur_landmineinfo)

                ---注册定时器
                if tableobj.all_unlimit_hb_timers[get_bury_landmine.hb_id] == nil then
                    tableobj.all_unlimit_hb_timers[get_bury_landmine.hb_id] = 0
                end
                local timerntc = {
                    table_index = tableobj.conf.table_index,
                    hb_id = get_bury_landmine.hb_id,
                }
                tableobj.all_unlimit_hb_timers[get_bury_landmine.hb_id] = timer.settimer(qhb_action_time * 100, "unlimit_qhb_outtime", timerntc)

                local base_idle_hbs = {
                    hb_id           = get_bury_landmine.hb_id,
                    rid             = get_bury_landmine.rid,
                    rolename        = get_bury_landmine.rolename,
                    logo            = get_bury_landmine.logo,
                    sex             = get_bury_landmine.sex,
                    total_money     = get_bury_landmine.total_money,
                    left_hb_num     = get_bury_landmine.total_hb_num,
                    all_hb_num      = get_bury_landmine.total_hb_num,
                    landmine_num    = get_bury_landmine.landmine_num,
                    times           = 1,
                    get_money       = 0,
                    qiang_hb_players = {},
                    add_qhb_players = {},
                }
                if get_bury_landmine.total_hb_num == 7 then
                    base_idle_hbs.times = 1.5
                elseif get_bury_landmine.total_hb_num == 10 then
                    base_idle_hbs.times = 1
                end
                table.insert(newhbs_data.idle_hbs, base_idle_hbs)
                ----填充todoN
                local todo_base = {
                    hb_id = get_bury_landmine.hb_id,
                    action_outtime = now_time + qhb_action_time,
                }
                table.insert(newhbs_tododata.qhbs, todo_base)
            end
            local getallrids = tablelogic.getallrids()
            server:send_notice_to_players(getallrids, "newhbsN", newhbs_data, nil, nil)

            for index, seat in ipairs(tableobj.seats) do
                if seat.rid ~= 0 then
                    local send_todo_data = tabletool.deepcopy(newhbs_tododata)
                    send_todo_data.rid = seat.rid
                    server:send_notice_to_players({seat.rid}, "todoN", send_todo_data, nil, nil)
                end
            end
        end
    end
end

function gamelogic.unlimit_qhb_over_check(gameobj)
    local tableobj = gameobj.tableobj
    local now_time = timetool.get_time()
    local tablelogic = server:get_logicbyname("tablelogic")
    --filelog.sys_error("----------gamelogic.unlimit_qhb_over_check-----------")
    for index, bury_landmine in ipairs(tableobj.can_qiang_landmineinfos) do
        if bury_landmine.action_outtime <= now_time or bury_landmine.total_hb_num == bury_landmine.already_qhb_num then
            bury_landmine.is_over = true
        end
    end
    local can_qiang_temp = tabletool.deepcopy(tableobj.can_qiang_landmineinfos)
    local is_over_landmines = {}
    tableobj.can_qiang_landmineinfos = {}
    for index, bury_landmine in ipairs(can_qiang_temp) do
        if bury_landmine.is_over == true then
            table.insert(is_over_landmines, bury_landmine)
        elseif bury_landmine.is_over == false then
            table.insert(tableobj.can_qiang_landmineinfos, bury_landmine)
        end
    end

    if #is_over_landmines > 0 then
        --filelog.sys_error("----------有符合结算条件的红包----------", now_time, is_over_landmines)
        tablelogic.nolimit_balance(is_over_landmines)
        gamelogic.add_newhb_nolimit(gameobj)
    end
end

return gamelogic